package com.ruoyi.system.utils;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.dom4j.io.SAXReader;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@Data
public class WechatOfficialUtils {

    public static String APP_ID;
    public static String SECRET;

    public static String getHzsAccessToken(String appid,String secret) {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        String response = HttpRequest.get(url).execute().body();
        Map<String, Object> accessTokenMap = JSONObject.parseObject(response, Map.class);
        return accessTokenMap.get("access_token").toString();
    }

    @Value("${wechat.public.appId}")
    public void setAppId(String appId) {
        APP_ID = appId;
    }

    @Value("${wechat.public.appSecret}")
    public void setSecret(String secret) {
        SECRET = secret;
    }

    public static String getAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APP_ID + "&secret=" + SECRET;
        String response = HttpRequest.get(url).execute().body();
        Map<String, Object> accessTokenMap = JSONObject.parseObject(response, Map.class);
        return accessTokenMap.get("access_token").toString();
    }


    public static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    public static String byteToHexStr(byte mByte) {
        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }


    public static Map<String, String> xmlToMap(HttpServletRequest httpServletRequest) {
        Map<String, String> resultMap = new LinkedHashMap<>();
        try {
            InputStream inputStream = httpServletRequest.getInputStream();
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            Element root = document.getRootElement();
            parseElement(root, resultMap);
            inputStream.close();
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
        return resultMap;
    }

    private static void parseElement(Element element, Map<String, String> map) {
        for (Object obj : element.elements()) {
            Element child = (Element) obj;
            if (child.isTextOnly()) {
                map.put(child.getName(), child.getTextTrim());
            } else {
                parseElement(child, map);
            }
        }
    }

    /**
     * JAVA对象转xml
     * @param object java对象
     * @param <T>
     * @return xml字符串
     * @throws JAXBException
     */
    public static <T> String convertXml(T object){
        try {
            JAXBContext context = JAXBContext.newInstance(object.getClass());
            // 创建 Marshaller装配器实例
            Marshaller marshaller = context.createMarshaller();
            // 可以设置的属性参见方法：com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.setProperty()
            marshaller.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.name());
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
            // 指定xml文件头
            //marshaller.setProperty("com.sun.xml.internal.bind.xmlHeaders", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            // 将xml写入流中
            marshaller.marshal(object, outputStream);
            // 将流转换成字符串
            return new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }


    /**
     * xml报文转java对象
     * @param xml xml报文
     * @param clazz java对象类
     * @param <E>
     * @return java对象
     * @throws JAXBException
     */
    public static <E> E convertObject(String xml, Class<E> clazz) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(clazz);
        // 创建unmarshaller解组器实例
        Unmarshaller unmarshaller = context.createUnmarshaller();
        StringReader stringReader = new StringReader(xml);
        return (E) unmarshaller.unmarshal(stringReader);
    }

    /**
     * xml文件流转java对象
     * @param inputStream xml文件流
     * @param clazz java对象类型
     * @param <E>
     * @return java对象
     * @throws JAXBException
     */
    public static <E> E convertObject(InputStream inputStream, Class<E> clazz) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(clazz);
        // 创建unmarshaller解组器实例
        Unmarshaller unmarshaller = context.createUnmarshaller();
        return (E) unmarshaller.unmarshal(inputStream);
    }

}